查看原文
其他

解析Web缓存及其最佳实践

前端小贾 前端学苑 2021-07-15

关注“前端学苑” ,坚持每天进步一点点


「~web缓存解析~」

缓存一直以来都是用来提高性能的一项必不可少的技术,利用这项技术可以很好地提高web的性能。缓存可以很有效地降低网络的时延,同时也会减少大量请求对于服务器的压力。 

一、为什么要用缓存

一般针对静态资源如CSS,JS,图片等使用缓存,原因如下:

1) 请求更快:通过将内容缓存在本地浏览器或距离最近的缓存服务器(如CDN),在不影响网站交互的前提下可以大大加快网站加载速度。

2) 节省带宽:对于已缓存的文件,可以减少请求带宽甚至无需请求网络。

3) 降低服务器压力:在大量用户并发请求的情况下,服务器的性能受到限制,此时将一些静态资源放置在网络的多个节点,可以起到均衡负载的作用,降低服务器的压力。


「~前端缓存导图~」


二、前端缓存技术方案,主要分为http缓存和浏览器缓存

HTML Meta标签控制缓存(非HTTP协议定义)

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。


1、HTTP缓存

HTTP头信息控制缓存是通过Expires(强缓存)、Cache-control(强缓存)、Last-Modified/If-Modified-Since(协商缓存)、Etag/If-None-Match(协商缓存)实现。


强缓存

强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。


1)Expires

Expires(http1.0的规范)表示资源过期时间的header,它描述的是一个绝对时间,由服务器返回,用GMT格式的字符串表示。

例如:当Expires: Wed, 22 Oct 2018 08:41:00 GMT时表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期,需要再次请求。

读取缓存数据条件:缓存过期时间(服务器的)< 当前时间(客户端的)

2)Cache-Control

Cathe-Control(http1.1规范)描述的是一个相对时间,在进行缓存命中的时候,都是利用客户端时间进行判断,所以相比较Expires,Cache-Control的缓存管理更有效,安全一些。

例如:当Cache-Control:max-age=300时,则代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存。缓存5分钟后就过期,需要重新请求。

读取缓存数据条件:上次缓存时间(客户端的)+max-age < 当前时间(客户端的)

说明:两者同时存在的话,Cache-Control优先级高于Expires;


协商缓存

协商缓存:会发请求到服务器。控制协商缓存可以通过设置两种 HTTP Header 字段实现:Last-Modify/If-Modified-Since 和 Etag/If-None-Match,这两个字段是成对使用的。


1)Last-Modify/If-Modified-Since

1) 浏览器在第一次访问资源时,服务器返回资源的同时,在response header中添加 Last-Modified的header,值是这个资源在服务器上的最后修改时间,浏览器接收后缓存文件和header;

2) 浏览器下一次请求这个资源,浏览器检测到有 Last-Modified这个header,于是添加If-Modified-Since这个header,值就是Last-Modified中的值;

3) 服务器再次收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回304和空的响应体,直接从缓存读取,

4) 如果If-Modified-Since的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200。

2)ETag和If-None-Match

1) Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。

2) 浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,

3) 服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。

4) 如果服务器发现ETag匹配不上,那么直接以常规GET 200 形式将新的资源(当然也包括了新的ETag)发给客户端;

5) 如果ETag是一致的,则直接返回304知会客户端直接使用本地缓存即可。


使用缓存流程,从浏览器请求到展示资源的过程:

浏览器缓存机制,其实主要就是HTTP协议定义的缓存机制(如:Expires;Cache-control等)。


2、浏览器缓存

1)存储 (storage)

简单的缓存方式有sessionStorage、localStorage和cookie。

共同点:都是保存在浏览器端,且同源的。

区别:

数据传输方面:

在每个http请求中都会附加cookie信息,cookie中的信息能够被推送到服务器端;

而sessionStorage和localStorage不会被推送到服务器端。

存储大小不同:

cookie最大支持4KB,而sessionStorage和localStorage一般在2.5~10MB

生命周期:

默认情况下,cookie开始于浏览器启动,结束于浏览器关闭,但是可以手动设置cookie的过期时间,同时,到期后被删除;

而对于localStorage,没有过期时间,原则上只要不手动删除,其会一直被保存在本地上;sessionStorage的数据关闭浏览器时清除

被创造的初衷不同:

sessionStorage和localStorage都属于WebStorage,创建他们的目的就是用于存储客户端数据;

而cookie最早在网景的浏览器中被支持,主要目的是为了辨别用户身份而存储在本地终端的数据。


2)前端数据库

前端数据库有WebSql和IndexDB,其中WebSql被规范废弃,他们都有大约50MB的最大容量,可以理解为localStorage的加强版。


3)应用缓存

应用缓存主要是通过manifest文件来注册被缓存的静态资源,已经被废弃,因为他的设计有些不合理的地方,他在缓存静态文件的同时,也会默认缓存html文件。这导致页面的更新只能通过manifest文件中的版本号来决定。所以,应用缓存只适合那种常年不变化的静态网站。如此的不方便,也是被废弃的重要原因。


4)Service Worker

Service Worker本质上也是浏览器缓存资源用的,只不过他不仅仅是cache,也是通过worker的方式来进一步优化。


基于h5的web worker,所以绝对不会阻碍当前js线程的执行,sw最重要的工作原理就是

1、后台线程:独立于当前网页线程;

2、网络代理:在网页发起请求时代理,来缓存文件;

兼容性:

基本上新版浏览器还是兼容滴。之前是只有chrome和firefox支持,现在微软和苹果也相继支持了。


详细资料从这里开始~~~


PWA

PWA全称Progressive Web App,即渐进式WEB应用。

PWA 主要功能:

1) web App Manifest 实现添加至主屏幕,

2) Service Worker 实现离线缓存, (主要功能)

3) push Notification 实现消息推送。


PWA项目实践:

vue cli 3.0中pwa使用了第三方库workbox,Web App 静态资源和请求结果的本地存储的解决方案。

workbox 是由谷歌浏览器团队发布,用来协助创建 PWA 应用的 JavaScript 库。

此时项目中关于PWA的文件如下:

1、package.json中引用了register-service-worker插件2、根目录下有registerServiceWorker.js3、public文件夹下有manifest.json,可以根据需要修改其中的内容module.exports = {pwa: { // configure the workbox plugin workboxPluginMode: 'InjectManifest', workboxOptions: { // swSrc is required in InjectManifest mode. swSrc: 'src/pwa/service-worker.js' } }}

1、 web App Manifest 实现添加至主屏幕

web App Manifest 作为PWA 的 户口本。

web App Manifest,即通过一个清单文件向浏览器暴露 web 应用的元数据,包括名字、icon的URL等,以备浏览器使用,比如在添加至主屏或推送通知时暴露给操作系统,从而增强web应用与操作系统的集成能力。

W3C web App Manifest

1) scope: 定义了web 应用的浏览作用域,比如作用域外的URL 就会打开浏览器而不会在当前PWA里继续浏览。

2) start_url: 定义了一个 PWA的入口页面。

3) orientation: 锁定屏幕旋转。

4) theme_color/background_color:主题色与背景色,用于配置一些可定制的操作系统UI 以提高用户体验。

比如:Android的状态栏,任务栏等。


2、Service Worker 实现离线缓存

LocalServer

1) 让 web应用离线使用的第一次尝试。

2) 2007年,为了让自家的 Gmail、youtube、Google Reader等web应用可以在本地存储数据与离线执行,Google开发了一个浏览器拓展来增强web应用—— Google Gears

3) 在Gears API中,通过向localServer 模块提交一个缓存文件清单来实现离线支持。

Application Cache

1) 让web 应用离线使用的第二次尝试

2) 在localServer的基础上进一步发展

3) 缺点:不可编程、无法清理缓存、几乎没有路由机制等

Service Worker

1) 让web 应用离线使用的第三次尝试

2) 可编程的 Web Worker

3) 像一个位于浏览器与网络之间的客户端代理,可以拦截、处理、响应流的HTTP 请求 (注:浏览器的nginx)

4) 配合Cache Storage APi,可以自由管理 HTTP 请求文件粒度的缓存

Service Worker  缓存策略

Service Worker 出于安全性和其实现原理,在使用的时候有一定的前提条件。

1、要求 HTTPS 的环境或localhost

2、Service Worker 的缓存机制是依赖 Cache API 实现的

3、依赖 HTML5 fetch API

4、依赖 Promise 实现

重要说明:

Service Worker 是支撑PWA作为 下一代 web 应用模型 的最核心技术。Service Worker将在未来十年里成为 web 客户端技术工程化的兵家必争之地。


三、push Notification 实现消息推送

1) push API 的出现则让推送服务具备了向 web应用推送消息的能力。

2) push API 不依赖 web 应用与浏览器UI存活,所以即使是在web 应用与浏览器未被用户打开的时候,也可以通过后台进程接受推送消息并调用 Notification API 向用户发出通知。

觉得本文对你有帮助?请分享给更多人

关注「前端学苑」加星标,提升前端技能

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存